import { Column, CreateDateColumn, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, OneToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
import Decimal from 'decimal.js';
import { Project } from './project.entity';
import { Security } from './security.entity';
import { Account } from '@/account/entity/account.entity';
import { StageFunding } from './stageFunding.entity';
import { InvestFunding } from './investFunding.entity';
import { dateTransformer, decimalTransformer } from './utils';

export enum StageStatus {
  DRAFT = 'draft',
  OPERATING = 'operating',
  DEFAULT ='default',
  PERFORMING = "performing",
  DISCHARGED = "discharged",
  EXTENSION= "extension",
  LOAN_AMENDMENT= "loanAmendment",
  SPECIAL = "special mention",
  FINISHED = 'finished'
}

export enum RankingType {
  FIRST_MORTAGE = '1st Mortgage',
  SECOND_MORTAGE = '2nd Mortgage',
  MIXED = 'mixed'
}

export enum InterstMethod {
  DAILY = 'daily',
  MONTHLY = 'monthly',
  COMPOUND = 'compound',
  FIX = 'fix'
}

export enum LineFeeMethod {
  DAILY = 'daily',
  MONTHLY = 'monthly',
}

export enum LoanPurposeSelect {
  Bridging = 'Bridging',
  Construction = 'Construction',
  EquityRelease = 'Equity Release',
  Extension = 'Extension',
  PropertySettlement = 'Property Settlement',
  Purchasing = 'Purchasing',
  RedrawFacility = 'Redraw Facility',
  Refinance = 'Refinance',
  RollOver = 'Roll-over',
  WorkingCapital = 'Working Capital',
}
export enum ExitStrategySelect {
  CashflowIncome = 'Cashflow Income',
  PropertySales = 'Property Sales',
  Refinance = 'Refinance',
}


@Entity()
export class Stage {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  sn: string

  @Column({name: 'project_id'})
  projectId: number

  @ManyToOne(type => Project, (project) => project.stages)
  @JoinColumn({name: 'project_id'})
  project: Project;

  @Column({nullable: true})
  projectName: string;

  @Column()
  status: StageStatus

  @Column()
  product: string

  @Column({type: 'text', nullable: true})
  infoCn?: string

  @Column({type: 'text', nullable: true})
  infoEn: string

  @Column({nullable: true})
  mainImg?: string

  @Column({nullable: true})
  img?: string

  @Column({ type: 'simple-json', nullable: true })
  detailImg?: string[]

  @Column()
  ranking: RankingType

  @Column()
  interestMethod: InterstMethod

  @Column({default: 'monthly'})
  lineFeeMethod: LineFeeMethod

  @Column({length: 2048, nullable: true})
  investmentStatus?: string

  @Column({length: 2048})
  loanPurpose: string

  @Column({nullable: true})
  loanPurposeSelect?: string

  @Column({length: 2048})
  exitStrategy: string
  
  @Column({nullable: true})
  exitStrategySelect: string

  @Column({ type: 'date', transformer: dateTransformer, nullable: true })
  loanExpiryDate?: Date

  @Column({length: 2048, nullable: true})
  loanTier?: string

  @Column({length: 2048, nullable: true})
  urbanicity?: string

  @Column({length: 2048, nullable: true})
  loanAlteration?: string

  @Column({nullable: true})
  LVR?: string;

  @Column({nullable: true})
  maxLVR?: string;

  @Column({nullable: true})
  loanTerm?: string;

  @Column()
  loanMaxTerm: number;

  @Column()
  loanMinTerm: number;

  @Column({ type: 'date', transformer: dateTransformer, nullable: true })
  instructionDate?: Date;

  @Column({ type: 'date', transformer: dateTransformer })
  loanStartDate: Date;

  @Column({ type: 'date', transformer: dateTransformer })
  loanRepaymentDate: Date;

  @Column({ type: 'decimal', precision: 20, scale: 4, transformer: decimalTransformer})
  targetTotalInvestment: Decimal;

  @Column({ type: 'decimal', precision: 20, scale: 4, transformer: decimalTransformer})
  minInvestment: Decimal;

  @Column({ type: 'date', transformer: dateTransformer })
  investStartDate: Date;

  @Column({ type: 'date', transformer: dateTransformer })
  investRepaymentDate: Date;

  @Column({ type: 'decimal', precision: 20, scale: 4, transformer: decimalTransformer})
  interestRate: Decimal

  @Column({ type: 'decimal', precision: 20, scale: 4, transformer: decimalTransformer})
  defaultRate: Decimal

  @Column({ type: 'decimal', precision: 20, scale: 4, transformer: decimalTransformer})
  lineFeeRate: Decimal

  @Column({ type: 'decimal', precision: 20, scale: 4, transformer: decimalTransformer, nullable: true})
  firstRankingAmount?: Decimal

  @Column({ type: 'decimal', precision: 20, scale: 4, transformer: decimalTransformer})
  loanAmount: Decimal

  @Column({ type: 'decimal', precision: 20, scale: 4, transformer: decimalTransformer})
  totalExitLoan: Decimal

  // @Column({name: 'security_id'})
  // securityId: number

  @ManyToMany(type => Security, security => security.stages)
  @JoinTable({
    name: 'stage_securities_security',
    joinColumn: {
      name: 'stageId',
      referencedColumnName: 'id',
    },
    inverseJoinColumn: {
      name: 'securityId',
      referencedColumnName: 'id',
    },
  })
  securities: Security[]

  @Column({ type: 'decimal', precision: 20, scale: 4, transformer: decimalTransformer})
  totalSecurityValue?: Decimal

  @ManyToMany(type=>Account, (a)=>a.sponsorStages, { cascade: true })
  @JoinTable()
  sponsors: Account[]

  @ManyToMany(type=>Account, (a)=>a.lenderStages, { cascade: true })
  @JoinTable()
  lenders: Account[]

  @ManyToMany(type=>Account, (a)=>a.brokerStages, { cascade: true })
  @JoinTable()
  brokers: Account[]

  @ManyToMany(type=>Account, (a)=>a.lawyerStages, { cascade: true })
  @JoinTable()
  lawyers: Account[]

  @ManyToMany(type=>Account, (a)=>a.favoriteStages, { cascade: true })
  @JoinTable()
  favoritedBy: Account[]

  @Column({name: 'management_fee_collector_id', nullable: true})
  managementFeeCollectorId?: number

  // @ManyToOne(type=>Account, (a)=>a.manageStages, { cascade: true })
  // @JoinColumn({name: 'management_fee_collector_id'})
  // managementFeeCollector: Account

  @OneToMany(type=>StageFunding, (a)=>a.stage, { cascade: true })
  fundings: StageFunding[]

  @OneToMany(type=>InvestFunding, (a)=>a.stage)
  investments: InvestFunding[]

  @OneToMany(type=>InvestFunding, (a)=>a.stage)
  transferTo: InvestFunding[]

  @OneToMany(type=>InvestFunding, (a)=>a.stage)
  transferFrom: InvestFunding[]

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;
}
